#include "FlashLog.h"
#include "timestamp.h"
#include <stdarg.h>

LogFlashData_st g_flash_log = {0};

int8_t log_flash_print(const char* ps8Format, ...)
{
    if(g_flash_log.length+1 >= LOG_FLASH_DATA_LENGTH)
    {
        printf("%s overlength\n",__func__);
        return -1;
    }
    else if(LOG_FLASH_HEADER_MAGIC == g_flash_log.magic)
    {
        memset(&g_flash_log,0,CMBACKTRACE_SIZE);
    }
    int32_t  s32Size = 0;
    uint16_t log_max_len = LOG_FLASH_DATA_LENGTH -  - 1;
    if(log_max_len > LOG_FLASH_PRINT_MAX)
    {
        log_max_len = LOG_FLASH_PRINT_MAX;
    }
    va_list  ap;
    va_start(ap, ps8Format);
    s32Size = vsnprintf((char*)&g_flash_log.data[g_flash_log.length+1],log_max_len, ps8Format, ap);
    va_end(ap);
    if (s32Size < 0)
    {
        printf("%s not enough:%ld\n",__func__,s32Size);
        return -3;
    }
    else if(s32Size > LOG_FLASH_PRINT_MAX)
    {
        s32Size = LOG_FLASH_PRINT_MAX;
    }
    g_flash_log.data[g_flash_log.length] = s32Size;
    g_flash_log.length += s32Size + 1;
    return 0;
} 

int8_t log_flash_store(void)
{
    g_flash_log.magic = LOG_FLASH_HEADER_MAGIC;
    g_flash_log.check_sum = 0;
    for(uint16_t i = 0;i < g_flash_log.length;i++)
    {
        g_flash_log.check_sum += g_flash_log.data[i];
    }
    int8_t ret = flash_erase(CMBACKTRACE_START_ADDR,CMBACKTRACE_SIZE);
    if(ret)
    {
        printf("%s erase failed:%d\n",__func__,ret);
        return ret;
    }
    ret = flash_write(CMBACKTRACE_START_ADDR,(uint8_t *)&g_flash_log,g_flash_log.length+LOG_FLASH_HEADER_LEN);
    if(ret)
    {
        printf("%s write failed:%d\n",__func__,ret);
        return ret;
    }
    printf("%s success\n",__func__);
    return 0;
}

int8_t log_flash_recover(void)
{
    int8_t ret;
    uint32_t check_sum;
    flash_read(CMBACKTRACE_START_ADDR,(uint8_t *)&g_flash_log,CMBACKTRACE_SIZE);
    if(LOG_FLASH_HEADER_MAGIC != g_flash_log.magic)
    {
        memset(&g_flash_log,0,CMBACKTRACE_SIZE);
        ret = -1;
    }
    else if(g_flash_log.length > LOG_FLASH_DATA_LENGTH)
    {
        memset(&g_flash_log,0,CMBACKTRACE_SIZE);
        ret = -2;
    }
    else if(g_flash_log.flag != LOG_FLAG_EMTPY)
    {
        memset(&g_flash_log,0,CMBACKTRACE_SIZE);
        ret = -3;
    }
    else
    {
        check_sum = 0;
        for(volatile uint16_t i = 0;i < g_flash_log.length;i++)
        {
            check_sum += g_flash_log.data[i];
        }
        if(check_sum == g_flash_log.check_sum)
        {
            ret = 0;
        }
        else
        {
            ret =-4;
        }
    }
    if(ret)
    {
        memset(&g_flash_log,0,CMBACKTRACE_SIZE);
    }
    return ret;
}

int8_t log_flash_clear(void)
{
    uint32_t log_flag = LOG_FLAG_CLEAR;
    int8_t ret = flash_write(CMBACKTRACE_START_ADDR+CMBACKTRACE_SIZE-4,(uint8_t *)&log_flag,4);
    if(ret)
    {
        return ret;
    }
    memset(&g_flash_log,0,CMBACKTRACE_SIZE);
    return 0;
}

LogFlashData_st *log_flash_get(void)
{
    return &g_flash_log;
}